/**
 *  功能：DS18B20 温度监控配置
 *  作者：tuut
 *  时间：2023-11-28
 *  描述：
 *      1.设备初始化
 *      2.设备周边温度读取
 *      3.测试官方方法的使用
*/
#include "Sketch_oct31b_ds18b20.h"  // DS18B20 设备引用 温度检测设备
#include <Arduino.h>
float findDevice(int pin);
int err_count = 0;
/****************************************DS18B20 part****************************************/
Sketch_oct31b_ds18b20::Sketch_oct31b_ds18b20() {
  Serial.println("Sketch_oct31b_ds18b20 Object Created.");
  ONE_WIRE_BUS_PIN = Ds18B20SensorPin;
}

Sketch_oct31b_ds18b20::Sketch_oct31b_ds18b20(int one_wire_bus_pin) {
  Serial.println("Sketch_oct31b_ds18b20 Object Created.");
  ONE_WIRE_BUS_PIN = one_wire_bus_pin;
}

Sketch_oct31b_ds18b20::~Sketch_oct31b_ds18b20() {
  Serial.println("Sketch_oct31b_ds18b20 Object Deleted.");
}

int Sketch_oct31b_ds18b20::getPin() {
  return ONE_WIRE_BUS_PIN;
}

/**
 * 功能描述：初始化DS18B20温度探测棒
 */
void Sketch_oct31b_ds18b20::initDS18b60DevManager() {
  Serial.print("Load Device on Pin:");
  Serial.println(ONE_WIRE_BUS_PIN);
  // ONE_WIRE_BUS_PIN = 14;
  oneWire = OneWire(ONE_WIRE_BUS_PIN);
  // 注册一个Ds18b20传感器
  sensors = DallasTemperature(&oneWire);
  cal_delayStart = millis();
  Serial.println("Dallas Temperature IC Control Library Demo");
  // 搜索本地DS18b20设备
  Serial.print("本地设备...");
  // Start up the library
  sensors.begin();
  Serial.print("找到 ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" 设备.");
  // 报告DS18b20设备电源状态
  Serial.print("电源状态: ");
  if (sensors.isParasitePowerMode()) Serial.println("打开");
  else Serial.println("关闭");
  if (!sensors.getAddress(insideThermometer, 0)) {
    Serial.println("不能找到设备[0]地址");
  } else {
    // 显示总线上设备0的地址
    Serial.print("设备 [0] 地址: ");
    printAddress(insideThermometer);
    // set the resolution to 9 bit per device
    sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
    Serial.print("Device 0 Resolution: ");
    Serial.print(sensors.getResolution(insideThermometer), DEC);  // 获取精度值
    Serial.println();
  }
  if (!sensors.getAddress(outsideThermometer, 1)) {
    Serial.println("不能找到设备[1]地址");
  } else {
    // 显示总线上设备1的地址
    Serial.print("设备 [1] 地址: ");
    printAddress(outsideThermometer);
    Serial.println();
    // set the resolution to 9 bit per device
    sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);
    Serial.print("Device 1 Resolution: ");
    Serial.print(sensors.getResolution(outsideThermometer), DEC);
    Serial.println();
  }
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();  //发送温度测量请求命令
  Serial.println("DONE");
}

void Sketch_oct31b_ds18b20::initDev() {
  findDevice(ONE_WIRE_BUS_PIN);
}

float findDevice(int pin) {
  OneWire ds = OneWire(pin);
  byte i;
  byte present = 0;
  byte type_s;
  byte data[9];
  byte addr[8];
  float celsius, fahrenheit;
  if (!ds.search(addr)) {
    if (err_count == 5) {
      return 0;
    }
    err_count += 1;
    Serial.println("No more addresses.");
    ds.reset_search();
    delay(250);
    return 0;
  } else {
    err_count = 0;
  }

  // Serial.print("ROM =");
  // for (i = 0; i < 8; i++) {
  //   Serial.write(' ');
  //   Serial.print(addr[i], HEX);
  // }

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return 0;
  }
  // Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      // Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      // Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      // Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return 0;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);  // start conversion, with parasite power on at the end

  delay(1000);  // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);  // Read Scratchpad

  // Serial.print("  Data = ");
  // Serial.print(present, HEX);
  // Serial.print(" ");
  for (i = 0; i < 9; i++) {  // we need 9 bytes
    data[i] = ds.read();
    // Serial.print(data[i], HEX);
    // Serial.print(" ");
  }
  // Serial.print(" CRC=");
  // Serial.print(OneWire::crc8(data, 8), HEX);
  // Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;  // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;       // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3;  // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1;  // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  // Serial.print("  Temperature = ");
  // Serial.print(celsius);
  // Serial.print(" Celsius, ");
  // Serial.print(fahrenheit);
  // Serial.println(" Fahrenheit");
  return celsius;
}

void Sketch_oct31b_ds18b20::loadDS18B20API(long _interval) {
  if (millis() - cal_delayStart >= _interval) {
    for (int x = 0; x <= 5; x++) {
      Serial.print("-----");
      delay(100);
    }
    Serial.println("");
    Serial.print("[{'outsideTemperature':{");
    str_outsideTemp = String(printData(outsideThermometer), 1);
    Serial.print("}}]");
    Serial.println("");
    Serial.print("[{'insideTemperature':{");
    str_insideTemp = String(printData(insideThermometer), 1);
    Serial.print("}}]");
    Serial.println("");
    for (int x = 0; x <= 5; x++) {
      Serial.print("-----");
      delay(100);
    }
    Serial.println("");
    cal_delayStart = millis();
  }
}

/*
 * Main function, get and show the temperature
 */
float Sketch_oct31b_ds18b20::printData(DeviceAddress deviceAddress) {
  Serial.print("'Device_Address': '");
  printAddress(deviceAddress);
  Serial.print("', ");
  return printTemperature(deviceAddress);
}

/**
 * 功能描述：function to print a device address
 */
void Sketch_oct31b_ds18b20::printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

// function to print the temperature for a device
float Sketch_oct31b_ds18b20::printTemperature(DeviceAddress deviceAddress) {
  // method 1 - slower
  //Serial.print("Temp C: ");
  //Serial.print(sensors.getTempC(deviceAddress));
  //Serial.print(" Temp F: ");
  //Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit
  // method 2 - faster
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == DEVICE_DISCONNECTED_C) {
    // Serial.println("Error: Could not read temperature data");
    return 0;
  }
  Serial.print("'Temp_C': '");
  Serial.print(tempC);
  Serial.print("', 'Temp_F': '");
  Serial.print(DallasTemperature::toFahrenheit(tempC));  // Converts tempC to Fahrenheit
  Serial.print("'");
  return tempC;
}

float Sketch_oct31b_ds18b20::getDs18b20Temp() {
  return findDevice(ONE_WIRE_BUS_PIN);
}